using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;

namespace SeataNet.Core.Lock
{
    /// <summary>
    /// 全局锁管理器接口
    /// </summary>
    public interface IGlobalLockManager
    {
        /// <summary>
        /// 尝试获取锁
        /// </summary>
        Task<bool> TryAcquireLockAsync(GlobalLock lockInfo, int timeoutMs = 30000);

        /// <summary>
        /// 释放锁
        /// </summary>
        Task<bool> ReleaseLockAsync(string xid, long branchId);

        /// <summary>
        /// 批量释放锁
        /// </summary>
        Task<bool> ReleaseLocksByXidAsync(string xid);

        /// <summary>
        /// 查询锁
        /// </summary>
        Task<List<GlobalLock>> QueryLocksAsync(LockQuery query);

        /// <summary>
        /// 检查锁冲突
        /// </summary>
        Task<LockConflict> CheckLockConflictAsync(GlobalLock lockInfo);

        /// <summary>
        /// 检测死锁
        /// </summary>
        Task<DeadlockDetectionResult> DetectDeadlockAsync();

        /// <summary>
        /// 清理过期锁
        /// </summary>
        Task<int> CleanExpiredLocksAsync();
    }

    /// <summary>
    /// 基于内存的全局锁管理器实现
    /// </summary>
    public class InMemoryGlobalLockManager : IGlobalLockManager
    {
        private readonly ILogger<InMemoryGlobalLockManager> _logger;
        private readonly ConcurrentDictionary<string, GlobalLock> _locks;
        private readonly ConcurrentDictionary<string, List<string>> _xidLockMapping;
        private readonly SemaphoreSlim _lockSemaphore;

        // 等待队列：记录哪些事务正在等待哪个锁
        // Key: LockKey, Value: 等待该锁的XID列表
        private readonly ConcurrentDictionary<string, List<string>> _lockWaitQueue;

        public InMemoryGlobalLockManager(ILogger<InMemoryGlobalLockManager> logger)
        {
            _logger = logger;
            _locks = new ConcurrentDictionary<string, GlobalLock>();
            _xidLockMapping = new ConcurrentDictionary<string, List<string>>();
            _lockWaitQueue = new ConcurrentDictionary<string, List<string>>();
            _lockSemaphore = new SemaphoreSlim(1, 1);

            // 启动后台清理任务
            Task.Run(async () => await BackgroundCleanupTaskAsync());
        }

        public async Task<bool> TryAcquireLockAsync(GlobalLock lockInfo, int timeoutMs = 30000)
        {
            if (lockInfo == null)
            {
                _logger.LogWarning("锁信息为空");
                return false;
            }

            var lockKey = lockInfo.GetLockKey();
            _logger.LogDebug($"尝试获取全局锁: LockKey={lockKey}, XID={lockInfo.Xid}, BranchId={lockInfo.BranchId}");

            var startTime = DateTime.Now;
            var deadline = startTime.AddMilliseconds(timeoutMs);

            while (DateTime.Now < deadline)
            {
                await _lockSemaphore.WaitAsync();
                try
                {
                    // 检查锁是否已存在
                    if (_locks.TryGetValue(lockKey, out var existingLock))
                    {
                        // 如果是同一个事务，允许重入
                        if (existingLock.Xid == lockInfo.Xid && existingLock.BranchId == lockInfo.BranchId)
                        {
                            _logger.LogDebug($"锁重入成功: LockKey={lockKey}, XID={lockInfo.Xid}");
                            // 从等待队列移除（如果存在）
                            RemoveFromWaitQueue(lockKey, lockInfo.Xid);
                            return true;
                        }

                        // 检查锁是否过期
                        if (existingLock.IsExpired())
                        {
                            _logger.LogWarning($"检测到过期锁，清理: LockKey={lockKey}, XID={existingLock.Xid}");
                            _locks.TryRemove(lockKey, out _);
                            RemoveLockFromXidMapping(existingLock.Xid, lockKey);
                        }
                        else
                        {
                            // 将当前事务添加到等待队列
                            AddToWaitQueue(lockKey, lockInfo.Xid);

                            _logger.LogDebug($"锁冲突: LockKey={lockKey}, 当前持有者XID={existingLock.Xid}, 请求者XID={lockInfo.Xid}");
                            // 锁被其他事务持有，等待后重试
                            await Task.Delay(50);
                            continue;
                        }
                    }

                    // 获取锁成功
                    lockInfo.CreatedTime = DateTime.Now;
                    lockInfo.ExpireTime = DateTime.Now.AddMinutes(5); // 默认5分钟超时
                    lockInfo.Status = LockStatus.Locked;

                    _locks.TryAdd(lockKey, lockInfo);
                    AddLockToXidMapping(lockInfo.Xid, lockKey);

                    // 从等待队列移除
                    RemoveFromWaitQueue(lockKey, lockInfo.Xid);

                    _logger.LogInformation($"获取全局锁成功: LockKey={lockKey}, XID={lockInfo.Xid}, BranchId={lockInfo.BranchId}");
                    return true;
                }
                finally
                {
                    _lockSemaphore.Release();
                }
            }

            // 超时，从等待队列移除
            RemoveFromWaitQueue(lockKey, lockInfo.Xid);

            _logger.LogWarning($"获取全局锁超时: LockKey={lockKey}, XID={lockInfo.Xid}, Timeout={timeoutMs}ms");
            return false;
        }

        public async Task<bool> ReleaseLockAsync(string xid, long branchId)
        {
            _logger.LogDebug($"释放全局锁: XID={xid}, BranchId={branchId}");

            await _lockSemaphore.WaitAsync();
            try
            {
                var releasedCount = 0;

                foreach (var kvp in _locks)
                {
                    if (kvp.Value.Xid == xid && kvp.Value.BranchId == branchId)
                    {
                        if (_locks.TryRemove(kvp.Key, out _))
                        {
                            RemoveLockFromXidMapping(xid, kvp.Key);
                            releasedCount++;
                        }
                    }
                }

                _logger.LogInformation($"释放全局锁完成: XID={xid}, BranchId={branchId}, 释放数量={releasedCount}");
                return releasedCount > 0;
            }
            finally
            {
                _lockSemaphore.Release();
            }
        }

        public async Task<bool> ReleaseLocksByXidAsync(string xid)
        {
            _logger.LogDebug($"批量释放全局锁: XID={xid}");

            await _lockSemaphore.WaitAsync();
            try
            {
                if (!_xidLockMapping.TryGetValue(xid, out var lockKeys))
                {
                    _logger.LogDebug($"未找到XID对应的锁: XID={xid}");
                    return false;
                }

                var releasedCount = 0;
                foreach (var lockKey in lockKeys.ToList())
                {
                    if (_locks.TryRemove(lockKey, out _))
                    {
                        releasedCount++;

                        // 清理等待队列中对应的条目
                        _lockWaitQueue.TryRemove(lockKey, out _);
                    }
                }

                _xidLockMapping.TryRemove(xid, out _);

                _logger.LogInformation($"批量释放全局锁完成: XID={xid}, 释放数量={releasedCount}");
                return releasedCount > 0;
            }
            finally
            {
                _lockSemaphore.Release();
            }
        }

        public async Task<List<GlobalLock>> QueryLocksAsync(LockQuery query)
        {
            await Task.CompletedTask;

            var results = _locks.Values
                .Where(l =>
                    (string.IsNullOrEmpty(query.ResourceId) || l.ResourceId == query.ResourceId) &&
                    (string.IsNullOrEmpty(query.TableName) || l.TableName == query.TableName) &&
                    (string.IsNullOrEmpty(query.Xid) || l.Xid == query.Xid) &&
                    (!query.BranchId.HasValue || l.BranchId == query.BranchId.Value) &&
                    (!query.PrimaryKeys.Any() || query.PrimaryKeys.Contains(l.PrimaryKey)))
                .ToList();

            _logger.LogDebug($"查询锁: 找到{results.Count}个锁");
            return results;
        }

        public async Task<LockConflict> CheckLockConflictAsync(GlobalLock lockInfo)
        {
            await Task.CompletedTask;

            var lockKey = lockInfo.GetLockKey();

            if (_locks.TryGetValue(lockKey, out var existingLock))
            {
                if (existingLock.Xid != lockInfo.Xid || existingLock.BranchId != lockInfo.BranchId)
                {
                    return new LockConflict
                    {
                        LockKey = lockKey,
                        CurrentXid = existingLock.Xid,
                        CurrentBranchId = existingLock.BranchId,
                        RequestXid = lockInfo.Xid,
                        RequestBranchId = lockInfo.BranchId,
                        ConflictTime = DateTime.Now
                    };
                }
            }

            return null;
        }

        public async Task<DeadlockDetectionResult> DetectDeadlockAsync()
        {
            await _lockSemaphore.WaitAsync();
            try
            {
                // 构建等待图 (Wait-For Graph)
                // Key: 等待者XID, Value: 被等待的XID列表（即持有锁的XID）
                var waitGraph = new Dictionary<string, HashSet<string>>();

                // 遍历所有锁和等待队列，建立等待关系
                foreach (var lockEntry in _locks)
                {
                    var lockKey = lockEntry.Key;
                    var lockHolder = lockEntry.Value;

                    // 查找等待这个锁的事务
                    if (_lockWaitQueue.TryGetValue(lockKey, out var waiters))
                    {
                        foreach (var waiterXid in waiters)
                        {
                            // waiterXid 正在等待 lockHolder.Xid
                            // 在等待图中添加边: waiterXid -> lockHolder.Xid
                            if (!waitGraph.ContainsKey(waiterXid))
                            {
                                waitGraph[waiterXid] = new HashSet<string>();
                            }
                            waitGraph[waiterXid].Add(lockHolder.Xid);

                            _logger.LogTrace($"等待关系: {waiterXid} -> {lockHolder.Xid} (锁: {lockKey})");
                        }
                    }

                    // 确保所有持有锁的事务都在图中
                    if (!waitGraph.ContainsKey(lockHolder.Xid))
                    {
                        waitGraph[lockHolder.Xid] = new HashSet<string>();
                    }
                }

                // 使用DFS检测环路
                var visited = new HashSet<string>();
                var recursionStack = new HashSet<string>();
                var deadlockCycle = new List<string>();

                foreach (var node in waitGraph.Keys)
                {
                    if (!visited.Contains(node))
                    {
                        if (HasCycle(node, waitGraph, visited, recursionStack, deadlockCycle))
                        {
                            // 检测到死锁
                            _logger.LogWarning($"检测到死锁: 涉及事务 {string.Join(" -> ", deadlockCycle)}");

                            return new DeadlockDetectionResult
                            {
                                HasDeadlock = true,
                                DeadlockXids = deadlockCycle.Distinct().ToList(),
                                DetectionTime = DateTime.Now,
                                Description = $"检测到循环等待: {string.Join(" -> ", deadlockCycle)}"
                            };
                        }
                    }
                }

                _logger.LogDebug("未检测到死锁");
                return new DeadlockDetectionResult
                {
                    HasDeadlock = false,
                    DetectionTime = DateTime.Now,
                    Description = "未检测到死锁"
                };
            }
            finally
            {
                _lockSemaphore.Release();
            }
        }

        /// <summary>
        /// 使用DFS检测等待图中的环路
        /// </summary>
        private bool HasCycle(
            string node,
            Dictionary<string, HashSet<string>> graph,
            HashSet<string> visited,
            HashSet<string> recursionStack,
            List<string> cycle)
        {
            visited.Add(node);
            recursionStack.Add(node);

            // 检查当前节点的所有邻接节点
            if (graph.ContainsKey(node))
            {
                foreach (var neighbor in graph[node])
                {
                    if (!visited.Contains(neighbor))
                    {
                        // 递归检查邻接节点
                        if (HasCycle(neighbor, graph, visited, recursionStack, cycle))
                        {
                            cycle.Insert(0, node);
                            return true;
                        }
                    }
                    else if (recursionStack.Contains(neighbor))
                    {
                        // 发现环路
                        cycle.Add(neighbor);
                        cycle.Add(node);
                        return true;
                    }
                }
            }

            recursionStack.Remove(node);
            return false;
        }

        public async Task<int> CleanExpiredLocksAsync()
        {
            _logger.LogDebug("开始清理过期锁");

            await _lockSemaphore.WaitAsync();
            try
            {
                var expiredKeys = _locks
                    .Where(kvp => kvp.Value.IsExpired())
                    .Select(kvp => kvp.Key)
                    .ToList();

                var cleanedCount = 0;
                foreach (var key in expiredKeys)
                {
                    if (_locks.TryRemove(key, out var expiredLock))
                    {
                        RemoveLockFromXidMapping(expiredLock.Xid, key);
                        cleanedCount++;
                    }
                }

                if (cleanedCount > 0)
                {
                    _logger.LogInformation($"清理过期锁完成: 数量={cleanedCount}");
                }

                return cleanedCount;
            }
            finally
            {
                _lockSemaphore.Release();
            }
        }

        private void AddLockToXidMapping(string xid, string lockKey)
        {
            _xidLockMapping.AddOrUpdate(xid,
                new List<string> { lockKey },
                (key, existing) =>
                {
                    existing.Add(lockKey);
                    return existing;
                });
        }

        private void RemoveLockFromXidMapping(string xid, string lockKey)
        {
            if (_xidLockMapping.TryGetValue(xid, out var lockKeys))
            {
                lockKeys.Remove(lockKey);
                if (!lockKeys.Any())
                {
                    _xidLockMapping.TryRemove(xid, out _);
                }
            }
        }

        /// <summary>
        /// 添加事务到锁的等待队列
        /// </summary>
        private void AddToWaitQueue(string lockKey, string xid)
        {
            _lockWaitQueue.AddOrUpdate(lockKey,
                new List<string> { xid },
                (key, existing) =>
                {
                    if (!existing.Contains(xid))
                    {
                        existing.Add(xid);
                    }
                    return existing;
                });
        }

        /// <summary>
        /// 从锁的等待队列移除事务
        /// </summary>
        private void RemoveFromWaitQueue(string lockKey, string xid)
        {
            if (_lockWaitQueue.TryGetValue(lockKey, out var waiters))
            {
                waiters.Remove(xid);
                if (!waiters.Any())
                {
                    _lockWaitQueue.TryRemove(lockKey, out _);
                }
            }
        }

        private async Task BackgroundCleanupTaskAsync()
        {
            while (true)
            {
                try
                {
                    await Task.Delay(TimeSpan.FromMinutes(1));
                    await CleanExpiredLocksAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "后台清理任务异常");
                }
            }
        }
    }
}
